﻿#include "zen_gles3.h"
#include "zen_gles3_kit.h"

#pragma comment(lib, "libEGL.lib")
#pragma comment(lib, "libGLESv2.lib")

#include "zen_egl.h"
#include "zen_app_windows.h"
#include "zen_matrix.h"
#include "gles3/gl3.h"

class GLNode
{
	Zen::GL::Buffers<Zen::GL::EBufferType::ArrayBuffer, 3> buffer;
	Zen::GL::ShaderKit_aVuC skit;
	Zen::GL::ShaderKit_aVC skit_avc;
	Zen::GL::ShaderKit_aV_Tex skit_tex;
	Zen::GL::ShaderKit_aVCuC_Tex skit_vcc_tex;
	Zen::GL::Texture2D texture;
	Zen::GL::ShaderKit_aVuMC aVuMC;
	Zen::Mat4 mat4;
	float r = 0;
public:
	void Init()
	{
		float vertex[] = { 0.0, 0.0, 1.2, 1.2, 0,  0.5 };
		float vertex2[] = { -0.5, 0, 0.5, -0.5, 1.2, 0.5 };
		Zen::Point4 colors[] = { {1,1,1,1}, {0.2,0.3,1,1}, {0.3,1,1,1} };
		buffer.Generate<0>(sizeof(vertex), vertex);
		buffer.Generate<1>(sizeof(colors), colors);
		buffer.Generate<2>(sizeof(vertex2), vertex2);
		skit.BindDefaultProgram();
		skit_avc.BindDefaultProgram();
		skit_tex.BindDefaultProgram();
		skit_vcc_tex.BindDefaultProgram();
		aVuMC.BindDefaultProgram();

		mat4 = Zen::Mat4MakeZRotation(r);

		uint8_t pixels[20 * 20 * 3] = {};
		for (auto& c : pixels)
		{
			c = rand() % 256;
		}

		texture.Generate(Zen::EPixel::RGB, 20, 20, pixels);
	}
	void Draw()
	{
		using namespace Zen::GL;
		skit.Active();
		skit.Ready();
		buffer.Perform<0>();
		Render::SetVertexBuffer(skit.GetAVertex(), 2, EType::Float, false, 0, 0);
		Render::SetUniform(skit.GetAVertex(), Zen::Point4{ 0.5f, 0.5f, 0.2f, 1.f });
		Render::DrawArrays(EDrawMode::Triangle, 0, 3);

		r += 0.01f;
		mat4 = Zen::Mat4MakeZRotation(r);

		aVuMC.Active();
		aVuMC.Ready();
		buffer.Perform<0>();
		Render::SetVertexBuffer(aVuMC.GetAVertex(), 2, EType::Float, false, 0, 0);
		Render::SetUniform(aVuMC.GetUColor(), Zen::Point4{ 0.5f, 0.5f, 0.2f, 1.f });
		Render::SetUniform(aVuMC.GetUMatrix(), mat4);
		Render::DrawArrays(EDrawMode::Triangle, 0, 3);


		skit_avc.Active();
		buffer.Perform<2>();
		Render::SetVertexBuffer(skit_avc.GetAVertex(), 2, EType::Float, false, 0, 0);
		buffer.Perform<1>();
		Render::SetVertexBuffer(skit_avc.GetAColor(), 4, EType::Float, 0, 0, 0);
		Render::DrawArrays(EDrawMode::Triangle, 0, 3);

		skit_tex.Active();
		buffer.Perform<0>();
		Render::SetVertexBuffer(skit_tex.GetAVertex(), 2, EType::Float, 0, 0, 0);
		Render::SetVertexBuffer(skit_tex.GetATexCoord(), 2, EType::Float, 0, 0, 0);
		//texture.Generate
		Render::SetTextureSampler(0, Zen::GL::Sampler{ EMinMagFilter::Nearest, EMinMagFilter::Nearest });
		Render::SetTexture(skit_tex.GetUTex(), 0, texture.GetId());
		Render::DrawArrays(EDrawMode::Triangle, 0, 3);

		skit_vcc_tex.Active();
		buffer.Perform<0>();
		Render::SetVertexBuffer(skit_vcc_tex.GetAVertex(), 2, EType::Float, 0, 0, 0);
		Render::SetVertexBuffer(skit_vcc_tex.GetATexCoord(), 2, EType::Float, 0, 0, 0);
		buffer.Perform<1>();
		Render::SetVertexBuffer(skit_vcc_tex.GetAColor(), 4, EType::Float, 0, 0, 0);
		Render::SetTexture(skit_vcc_tex.GetUTex(), 0, texture.GetId());
		Render::SetUniform(skit_vcc_tex.GetUColor(), 1.f, 1.f, 1.f, 1.f);
		Render::DrawArrays(EDrawMode::Triangle, 0, 3);
	}
};

class AppD : public Zen::AppDelegate
{
	Zen::GL::Window* glWin{};
	GLNode* node;
public:
	virtual void OnLaunch(Zen::Point2 view_size) {
		//glWin = new Zen::GL::Window(Zen::AppWindows_::Only_()->GetHWindow());
		node = new GLNode;
		node->Init();
	}

	virtual void OnResize(Zen::Point2 view_size) {}

	virtual void OnPause() {}

	virtual void OnResume() {}

	virtual void OnUpdate() {}

	virtual void OnDraw() {
		//glClearColor(rand() % 100 / 100.f, rand() % 100 / 100.f, rand() % 100 / 100.f, 1);
		//glClear(GL_COLOR_BUFFER_BIT);
		node->Draw();
		//glWin->SwapBuffer();
	}

	virtual void OnExit() {}

};

std::shared_ptr<Zen::AppDelegate> ZenAppMain(Zen::AppConfig* config)
{
	config->WindowHeight = 400;
	config->WindowWidth = 400;
	config->FramesPerSecond = 60.f;
	config->Title = "I";
	return std::make_shared<AppD>();
}
